# encoding:utf-8
#qpy:console
import time
import datetime
import calendar
import base64
import json
from PIL import Image
import cv2
import numpy as np
import requests
import os
import ddddocr
from flask import Flask
from flask import request
path = "/tmp/"
#切图
def cut_image(image,num,len0=0):
    width, height = image.size
    item_width = int(width /num )
    box_list = []
    # (left, upper, right, lower)
    len0 = len0//2
    left = len0
    right = len0
    upper = len0
    lower = len0
    for i in range(0,num):#两重循环，生成9张图片基于原图的位置
        for j in range(0,num):
            if j == 0:
                left = 0
            else:
                left = len0 
            if (j +1) == num:
                right = 0
            else:
                right = len0
                
            if i == 0:
                upper = 0
            else:
                upper = len0 
            if (i +1) == num:
                lower = 0
            else:
                lower = len0
                
            box = (j*item_width + left,i*item_width + upper,(j+1)*item_width-right,(i+1)*item_width-lower)
            box_list.append(box)

    image_list = [image.crop(box) for box in box_list]
    return image_list

#保存
def save_images(image_list,filepath):      
    list_a = []
    index = 0
    for image in image_list:
        filepath = filepath + str(index) + '.png'
        list_a.append(filepath)
        image.save(path + filepath, 'PNG')
        index += 1
    return list_a

# 均值哈希算法
def aHash(img,shape=(10,10)):
    # 缩放为10*10
    img = cv2.resize(img, shape)
    # 转换为灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # s为像素和初值为0，hash_str为hash值初值为''
    s = 0
    hash_str = ''
    # 遍历累加求像素和
    for i in range(shape[0]):
        for j in range(shape[1]):
            s = s + gray[i, j]
    # 求平均灰度
    avg = s / 100
    # 灰度大于平均值为1相反为0生成图片的hash值
    for i in range(shape[0]):
        for j in range(shape[1]):
            if gray[i, j] > avg:
                hash_str = hash_str + '1'
            else:
                hash_str = hash_str + '0'
    return hash_str

# 差值感知算法
def dHash(img,shape=(10,10)):
    # 缩放10*11
    img = cv2.resize(img, (shape[0]+1, shape[1]))
    # 转换灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    hash_str = ''
    # 每行前一个像素大于后一个像素为1，相反为0，生成哈希
    for i in range(shape[0]):
        for j in range(shape[1]):
            if gray[i, j] > gray[i, j + 1]:
                hash_str = hash_str + '1'
            else:
                hash_str = hash_str + '0'
    return hash_str


# 感知哈希算法(pHash)
def pHash(img,shape=(10,10)):
    # 缩放32*32
    img = cv2.resize(img, (32, 32))  # , interpolation=cv2.INTER_CUBIC

    # 转换为灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 将灰度图转为浮点型，再进行dct变换
    dct = cv2.dct(np.float32(gray))
    # opencv实现的掩码操作
    dct_roi = dct[0:10, 0:10]

    hash = []
    avreage = np.mean(dct_roi)
    for i in range(dct_roi.shape[0]):
        for j in range(dct_roi.shape[1]):
            if dct_roi[i, j] > avreage:
                hash.append(1)
            else:
                hash.append(0)
    return hash


# 通过得到RGB每个通道的直方图来计算相似度
def classify_hist_with_split(image1, image2, size=(256, 256)):
    # 将图像resize后，分离为RGB三个通道，再计算每个通道的相似值
    image1 = cv2.resize(image1, size)
    image2 = cv2.resize(image2, size)
    sub_image1 = cv2.split(image1)
    sub_image2 = cv2.split(image2)
    sub_data = 0
    for im1, im2 in zip(sub_image1, sub_image2):
        sub_data += calculate(im1, im2)
    sub_data = sub_data / 3
    return sub_data


# 计算单通道的直方图的相似值
def calculate(image1, image2):
    hist1 = cv2.calcHist([image1], [0], None, [256], [0.0, 255.0])
    hist2 = cv2.calcHist([image2], [0], None, [256], [0.0, 255.0])
    # 计算直方图的重合度
    degree = 0
    for i in range(len(hist1)):
        if hist1[i] != hist2[i]:
            degree = degree + (1 - abs(hist1[i] - hist2[i]) / max(hist1[i], hist2[i]))
        else:
            degree = degree + 1
    degree = degree / len(hist1)
    return degree

# Hash值对比
def cmpHash(hash1, hash2,shape=(10,10)):
    n = 0
    # hash长度不同则返回-1代表传参出错
    if len(hash1)!=len(hash2):
        return -1
    # 遍历判断
    for i in range(len(hash1)):
        # 相等则n计数+1，n最终为相似度
        if hash1[i] == hash2[i]:
            n = n + 1
    return n/(shape[0]*shape[1])


#经测试均值哈希算法与三直方图算法相似度效果较好
def writePNG(url,num):    
    response = requests.get(url=url)
    imgpath = '123456' + str(num) + '.png'
    if os.path.exists(path+imgpath):
        os.remove(path+imgpath)        
    f = open(path+imgpath,'ab') #存储图片，多媒体文件需要参数b(二进制文件)
    f.write(response.content) #多媒体存储content
    f.close()
    return imgpath

#两个图片相似性比较 参数第一个为第一个图片，第二个为切分几分，第三个参数为第二个图片，第四个为和切分的第几个比较
def biJiao(data):    
    path1 = data[0]
    img1=cv2.imread(path + path1)
    hash1= aHash(img1)
    path2 = data[1]
    img2=cv2.imread(path + path2)
    hash2= aHash(img2)
    n=cmpHash(hash1,hash2)
    #n = classify_hist_with_split(img1, img2)    
    return n
#图片相似度比较    
def xiangSi(data):    
    #二维矩阵
    a = np.ones((9,9))
    list_a = []
    list_d = []
    n = 0
    list_b = []
    list_c = []
    imgName = writePNG(data["img"],999)
    filepath = "png"
    img = Image.open(path + imgName)
    image_list = cut_image(img,3,data["len0"])
    list_c = save_images(image_list,filepath)
    index = 0
    for key in data["thumb"]:
        imgName1 = writePNG(data["thumb"][key],index)
        list_b.append(imgName1)
        index+=1
    while n < 9:
        #相似度百分比
        num = 0.0
        index = 0
        #第几个
        ci = 0
        for key in data["thumb"]:
            params = [list_c[n],list_b[index]]
            m = biJiao(params)
            a[n][index] = m
            if m > num:
                num = m
                ci = index
            index+=1
        list_a.append(ci)
        n +=1
    myPrint(a)
    return list_a
#简单的图片验证码识别
def getCaptcha(content):
    ocr = ddddocr.DdddOcr()
    content = base64.b64decode(content.encode('utf-8'))
    res = ocr.classification(content)    
    myPrint(res)
    return res
    
def readFile(fileName):
    
    pathName = path+fileName
    if os.path.exists(pathName):
        with open(pathName,mode="r") as f:
            data = f.read()
    else:
        data= None
    try:
        data = json.loads(data)
    except Exception as e:
        print(str(e))
    return data

def writeFile(pathName,data):    
    pathName = path + pathName
    pathDir = pathName[0:pathName.rfind("/")]
    if isinstance(data,(list,dict)):
        text = json.dumps(data, indent=4, ensure_ascii=False)
    else:
        text = str(data)
    if os.path.exists(pathDir) == False:
        os.makedirs(pathDir)
    with open(pathName,mode="w+") as f:
        f.write(text)
    

def pushSMS(data):
    myList = ["建设银行"]
    company = data["company"]
    smsCode = data["smsCode"]
    fileName = "sms.json"       
    if company in myList:        
        dict_a={
        	  "smsKey":smsCode,
    	      "time":time.time()
        	}
        writeFile(fileName,dict_a)
        print("验证码已存储！" + smsCode)
    return smsCode
def getSMS():    
    fileName = "sms.json"
    data = readFile(fileName)
    if data == None:
        print("文件不存在")
        data={
        	  "smsKey":"000000",
        	  "time":0
        	} 
    print(data) 
    return data
    
def myPrint(data):
    if isinstance(data,(list,dict)):
        text = json.dumps(data, indent=4, ensure_ascii=False)
        print(text)
    else:
        print(str(data))
def excuteStr(evalStr,request):
    params = None
    if request.method == "POST":
        if request.content_type.startswith('application/json'):            
            params = request.json.get("data")
    print(evalStr)
    print(params)
    if params == None:
        evalStr += "()"
    else:
        evalStr += "(params)"
    state = False
    try:
        data = eval(evalStr)
        state = True
    except Exception as e:
        data = str(e)
    print(data)
    dict_a = {
    	    "data" : data,
    	    "state" : state
    	}
    return  dict_a
    